---
title: Getting Started
description: Setting up Zag UI machines in your project
---

Zag can be used within most JS frameworks like Vue, React, Svelte and Solid.

To get Zag running, you'll need to:

1. Install the machine for the component you're interested in. Let's say you
   want to use the `tooltip` machine.

```bash
npm install @zag-js/tooltip
# or
yarn add @zag-js/tooltip
```

2. Install the adapter for the framework of your choice. At the moment, Zag is
   available for React, Vue 3, Svelte and Solid.js. Let's say you use React.

```bash
npm install @zag-js/react
# or
yarn add @zag-js/react
```

> Congrats! You're ready to use tooltip machine in your project.

## Using the machine

Here's an example of the tooltip machine used in a React.js project.

```jsx
import * as tooltip from "@zag-js/tooltip"
import { useMachine, normalizeProps } from "@zag-js/react"

export function Tooltip() {
  const service = useMachine(tooltip.machine, { id: "1" })

  const api = tooltip.connect(service, normalizeProps)

  return (
    <>
      <button {...api.getTriggerProps()}>Hover me</button>
      {api.open && (
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>Tooltip</div>
        </div>
      )}
    </>
  )
}
```

### Usage with Vue 3 (JSX)

Zag works seamlessly with Vue's JSX approach. Here's how to use the same tooltip
logic in Vue:

```jsx
import * as tooltip from "@zag-js/tooltip"
import { normalizeProps, useMachine } from "@zag-js/vue"
import { computed, defineComponent, h, Fragment } from "vue"

export default defineComponent({
  name: "Tooltip",
  setup() {
    const service = useMachine(tooltip.machine, { id: "1" })
    const apiRef = computed(() => tooltip.connect(service, normalizeProps))

    return () => {
      const api = apiRef.current
      return (
        <>
          <div>
            <button {...api.getTriggerProps()}>Hover me</button>
            {api.open && (
              <div {...api.getPositionerProps()}>
                <div {...api.getContentProps()}>Tooltip</div>
              </div>
            )}
          </div>
        </>
      )
    }
  },
})
```

There are some extra functions that need to be used in order to make it work:

- `normalizeProps` - Converts the props of the component into the format that is
  compatible with Vue.
- `computed` - Ensures that the tooltip's `api` is always up to date with the
  current state of the machine.

### Usage with Solid.js

We love Solid.js and we've added support for it. Here's how to use the same
tooltip logic in Solid:

```jsx
import * as tooltip from "@zag-js/tooltip"
import { normalizeProps, useMachine } from "@zag-js/solid"
import { createMemo, createUniqueId, Show } from "solid-js"

export function Tooltip() {
  const service = useMachine(tooltip.machine, { id: createUniqueId() })

  const api = createMemo(() => tooltip.connect(service, normalizeProps))

  return (
    <div>
      <button {...api().getTriggerProps()}>Hover me</button>
      <Show when={api().open}>
        <div {...api().getPositionerProps()}>
          <div {...api().getContentProps()}>Tooltip</div>
        </div>
      </Show>
    </div>
  )
}
```

There are some extra functions that need to be used in order to make it work:

- `normalizeProps` - Converts the props of the component into the format that is
  compatible with Solid.
- `createMemo` - Ensures that the tooltip's `api` is always up to date with the
  current state of the machine.

### Usage with Svelte

Here's how to use the same tooltip logic in Svelte:

```html
<script lang="ts">
  import * as tooltip from "@zag-js/tooltip"
  import { useMachine, normalizeProps } from "@zag-js/svelte"

  const service = useMachine(tooltip.machine, { id: "1" })

  const api = $derived(tooltip.connect(service, normalizeProps))
</script>

<div>
  <button {...api.getTriggerProps()}>Hover me</button>
  {#if api.open}
  <div {...api.getPositionerProps()}>
    <div {...api.getContentProps()}>Tooltip</div>
  </div>
  {/if}
</div>
```

There are some extra functions that need to be used in order to make it work:

- `normalizeProps` - Converts the props of the component into the format that is
  compatible with Svelte.
- `$derived` - Ensures that the tooltip's `api` is always up to date with the
  current state of the machine.

### About prop normalization

There are subtle difference between how JSX attributes are named across
frameworks like React, Solid, Vue and Svelte. Here are some examples:

**Keydown listener**

- React and Solid: The keydown listener property is `onKeyDown`.
- Vue: The keydown listener property is `onKeydown`.

**Styles**

- React: Pass a numeric value for margin attributes like `{ marginBottom: 4 }`.
- Solid: It has to be `{ "margin-bottom": "4px" }`.
- Vue: You need to ensure the value is a string with unit.
  `{ marginBottom: "4px" }`.

These little nuances between frameworks are handled automatically when you use
`normalizeProps`.

> The goal of Zag is to help you abstract the interaction and accessibility
> patterns into a statechart so you never have to re-invent the wheel.

Thanks for reading! If you're curious about how state machines work, the next
page will give you a quick overview.
